package com.asiainfo.complier.editor;

import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;

import com.asiainfo.complier.conf.SysSetting;

public class AutoCompleteUI {

	private CoderEditor editor;
	private static JWindow window = new JWindow(SysSetting.MAIN_Frame);
	private static JavaKeyWordManager javaKeyWordManager = new JavaKeyWordManager();
	private JList lstBox;
	private boolean isShowUI = false;
	private int listSize = 0;
	private boolean bShowStop = false;
	private int offset = -1;
	private int offsetLength = -1;
	private SmartIndent indent;

	private static DefaultListModel lstModel = new DefaultListModel();

	public AutoCompleteUI(final CoderEditor editor) {

		this.editor = editor;
		indent = new SmartIndent(editor.getActiveEditor());
		window.setLayout(new BorderLayout());
		window.setFocusable(true);
		window.setSize(430, 100);
		lstBox = new JList();
		lstBox.setModel(lstModel);

		lstBox.setFocusable(true);
		lstBox.setAutoscrolls(true);
		lstBox.addKeyListener(new KeyAdapter() {

			public void keyReleased(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
					if (isShowUI) {
						bShowStop = true;
						window.setLocation(-2003, -2003);
						isShowUI = false;

					}
				} else if (e.getKeyCode() == KeyEvent.VK_ENTER) {

					Object obj = lstBox.getSelectedValue();

					if (obj != null) {
						Document doc = editor.getEditor().getDocument();
						try {
							if (offset != -1 && offsetLength != -1) {
								doc.remove(offset, offsetLength);
								doc.insertString(offset, obj.toString(), null);
								isShowUI = false;
								offset = -1;
								offsetLength = -1;

							}
							window.setLocation(-2003, -2003);

						} catch (BadLocationException e1) {

							e1.printStackTrace();
						}

					}
				}

			}

		});
		lstBox.addMouseListener(new MouseAdapter() {

			public void mouseClicked(MouseEvent e) {

				if (e.getClickCount() == 2) {

					Object obj = lstBox.getSelectedValue();

					if (obj != null) {
						Document doc = editor.getEditor().getDocument();
						try {
							if (offset != -1 && offsetLength != -1) {
								doc.remove(offset, offsetLength);
								doc.insertString(offset, obj.toString(), null);
								isShowUI = false;
								offset = -1;
								offsetLength = -1;

							}
							window.setLocation(-2003, -2003);

						} catch (BadLocationException e1) {

							e1.printStackTrace();
						}

					}
				}

			}
		});

		window.setLocation(-2002, -2002);
		JScrollPane pane = new JScrollPane();
		pane.getViewport().add(lstBox);
		pane.setFocusable(true);
		window.getContentPane().add(pane, BorderLayout.CENTER);

		window.setVisible(true);

		editor.getEditor().addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				if (isShowUI) {
					bShowStop = true;
					window.setLocation(-2003, -2003);
					isShowUI = false;

				}

			}
		});

		editor.getEditor().addAncestorListener(new AncestorListener() {

			 
			public void ancestorRemoved(AncestorEvent event) {
				if (isShowUI) {
					bShowStop = true;
					window.setLocation(-2003, -2003);
					isShowUI = false;

				}

			}

			 
			public void ancestorMoved(AncestorEvent event) {
				if (isShowUI) {
					bShowStop = true;
					window.setLocation(-2003, -2003);
					isShowUI = false;

				}

			}

			 
			public void ancestorAdded(AncestorEvent event) {
				if (isShowUI) {
					bShowStop = true;
					window.setLocation(-2003, -2003);
					isShowUI = false;

				}
			}
		});

		editor.getEditor().addKeyListener(new KeyAdapter() {

			@Override
			public void keyReleased(KeyEvent e) {
				if (bShowStop) {
					bShowStop = false;
					e.consume();
					return;
				}
				int pos = editor.getActiveEditor().getCaretPosition();

				Rectangle rc;
				try {
					String keyWord = getPosText(pos - 1);

					if (keyWord == null || keyWord.trim().length() == 0)
						return;
					boolean hasKeyWord = updatePopInfo(keyWord);

					if (hasKeyWord) {
						rc = editor.getActiveEditor().modelToView(
								pos - keyWord.length());
						Point point = new Point(rc.x, rc.y);
						SwingUtilities.convertPointToScreen(point,
								editor.getActiveEditor());
						LineEditor lineEditor = editor.getActiveEditor();
						Rectangle lineRc = lineEditor.getVisibleRect();
						Point pt = new Point(lineRc.x + lineRc.width, lineRc.y
								+ lineRc.height);
						SwingUtilities.convertPointToScreen(pt,
								editor.getActiveEditor());
						int width = pt.x;
						int height = pt.y;
						int x = point.x;
						int y = point.y + editor.getEditor().getRowHeight() + 2;
						if ((x + 430) > width)
							x = width - 430;
						if (y + 100 > height)
							y = point.y - 100;

						window.setLocation(x, y);
						isShowUI = true;
						offset = pos - keyWord.length();
						offsetLength = keyWord.length();

					} else {
						isShowUI = false;
						offset = -1;
						offsetLength = -1;
					}

				} catch (Exception ex) {
					ex.printStackTrace();

				}
			}

			@Override
			public void keyPressed(KeyEvent e) {

				bShowStop = false;

				if (isShowUI) {
					if (e.getKeyCode() == KeyEvent.VK_DOWN
							|| e.getKeyCode() == KeyEvent.VK_RIGHT) {
						int index = lstBox.getSelectedIndex();
						index++;
						if (index >= listSize) {
							index = 0;
						}

						Point point = lstBox.indexToLocation(index);
						Rectangle rc = new Rectangle(point.x, point.y, lstBox
								.getWidth(), lstBox.getHeight());
						lstBox.setSelectedIndex(index);
						lstBox.scrollRectToVisible(rc);

						e.consume();
						bShowStop = true;

					} else if (e.getKeyCode() == KeyEvent.VK_UP
							|| e.getKeyCode() == KeyEvent.VK_LEFT) {
						int index = lstBox.getSelectedIndex();
						index--;

						if (index <= 0) {
							index = 0;
						}

						Point point = lstBox.indexToLocation(index);
						Rectangle rc = new Rectangle(point.x, point.y, lstBox
								.getWidth(), lstBox.getHeight());
						lstBox.setSelectedIndex(index);
						lstBox.scrollRectToVisible(rc);

						e.consume();
						bShowStop = true;

					} else if (e.getKeyCode() == KeyEvent.VK_ENTER
							|| e.getKeyCode() == KeyEvent.VK_SPACE) {
						e.consume();
						Object obj = lstBox.getSelectedValue();
						if (obj != null) {

							Document doc = editor.getEditor().getDocument();

							try {
								if (offset != -1 && offsetLength != -1)
									doc.remove(offset, offsetLength);
								doc.insertString(offset, obj.toString(), null);
							} catch (BadLocationException e1) {

								e1.printStackTrace();
							}

						}
						bShowStop = true;
						window.setLocation(-2003, -2003);
						isShowUI = false;
					} else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
						bShowStop = true;
						window.setLocation(-2003, -2003);
						isShowUI = false;

					}
				} else {
					if (e.getKeyCode() == KeyEvent.VK_ENTER) {
						int dot = editor.getActiveEditor().getCaret().getDot();
						if (dot < editor.getActiveEditor().getDocument()
								.getLength()) {
							indent.getIndent(dot);
							String empString = indent.toString();
							try {
								e.consume();
								editor.getActiveEditor().getDocument()
										.insertString(dot, empString, null);
								editor.getActiveEditor().moveCaretPosition(
										dot + empString.length());
							} catch (BadLocationException ex) {

								ex.printStackTrace();
							}

						}
					}
				}
			}

		});

	}

	/**
	 * update PopInfo UI
	 * 
	 * @param keyWord
	 * @return
	 */
	private boolean updatePopInfo(String keyWord) {
		return javaKeyWordManager.showAutoComplete(keyWord, this);
	}

	private String getPosText(int pos) {
		try {
			String curStr = editor.getActiveEditor().getDocument()
					.getText(pos, 1);

			if (!curStr.equals(" ")) {
				int sIndex = pos;

				while (true) {
					int index = pos--;

					if (index >= 0) {
						curStr = editor.getActiveEditor().getDocument()
								.getText(index, 1);
						if (curStr.equals("\n") || curStr.equals("\r")
								|| curStr.equals("\t") || curStr.equals(" ")
								|| curStr.equals("(") || curStr.equals(".")) {
							int length = sIndex - index + 1;
							return editor.getActiveEditor().getDocument()
									.getText(index + 1, length).trim();

						}
					} else {
						return editor.getActiveEditor().getDocument()
								.getText(0, pos).trim();
					}

				}
			} else {
				window.setLocation(-2003, -2030);
				return null;
			}

		} catch (BadLocationException e) {
			window.setLocation(-2003, -2003);
			e.printStackTrace();
			return null;
		}

	}

	/*
	 * setShowData
	 * 
	 * @param keyList
	 */
	public void setShowData(ArrayList<JavaKeyWord> keyList) {
		lstModel.clear();
		if (keyList.size() > 0) {

			for (JavaKeyWord javaKeyWord : keyList) {
				lstModel.addElement(javaKeyWord);
			}
			lstBox.setSelectedIndex(0);
			listSize = keyList.size();

		} else {
			listSize = 0;
			window.setLocation(-2003, -2003);
		}

	}
}
